﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Is.Net.Net {

/**
 * @author Hugi Þórðarson
 * @converted to C# Ingi Gauti Ragnarsson
 * 
 * Icelandic IP-addresses need regular updates: http://www.rix.is/is-as-nets.html
 */

public class IPRange {

        public static readonly char LF = '\n';
        private static readonly char DOT_PATTERN = '.';
		private static readonly char COMMA = ',';
        private List<SingleIPRange> ranges = new List<SingleIPRange>();
        private static IPRange _icelandicRange;

        public IPRange() {}

        public IPRange( String ip1, String ip2 ) {
                this.AddRange( ip1, ip2 );
        }

        public void AddRange( String ip1, String ip2 ) {

                if( ip1 != null && ip2 != null ) {
                        ranges.Add( new SingleIPRange( ip1, ip2 ) );
                }
        }

        public void AddRanges( String ip1, String ip2 ) {
                String[] firstIPs = ip1.Split( COMMA );
                String[] lastIPs = ip2.Split( COMMA );
                AddRanges( firstIPs, lastIPs );
        }

        public void AddRanges( String[] firstIPs, String[] lastIPs ) {
                for( int i = firstIPs.Length - 1; i >= 0; i-- ) {
                        AddRange( firstIPs[i], lastIPs[i] );
                }
        }

        public bool IsInRange( String ipAddress ) {

                if( ranges != null && ranges.Count > 0 ) {

                        foreach ( SingleIPRange sipr in ranges ) {
                                if( sipr.IsInRange( ipAddress ) )
                                        return true;
                        }
                }

                return false;
        }

        public static IPRange IcelandicRange() {

                if( _icelandicRange == null ) {
                        _icelandicRange = new IPRange();
                        _icelandicRange.AddRange( "62.145.128.1", "62.145.159.254" );
                        _icelandicRange.AddRange( "81.15.0.1", "81.15.127.254" );
                        _icelandicRange.AddRange( "213.181.96.1", "213.181.127.254" );
                        _icelandicRange.AddRange( "213.220.64.1", "213.220.127.254" );
                        _icelandicRange.AddRange( "193.4.58.1", "193.4.59.254" );
                        _icelandicRange.AddRange( "130.208.0.1", "130.208.255.254" );
                        _icelandicRange.AddRange( "155.91.74.1", "155.91.74.254" );
                        _icelandicRange.AddRange( "157.157.0.1", "157.157.255.254" );
                        _icelandicRange.AddRange( "157.157.139.1", "157.157.139.254" );
                        _icelandicRange.AddRange( "192.147.34.1", "192.147.34.254" );
                        _icelandicRange.AddRange( "194.105.224.1", "194.105.255.254" );
                        _icelandicRange.AddRange( "204.219.180.1", "204.219.183.254" );
                        _icelandicRange.AddRange( "204.219.220.1", "204.219.223.254" );
                        _icelandicRange.AddRange( "212.30.192.1", "212.30.223.254" );
                        _icelandicRange.AddRange( "213.167.128.1", "213.167.159.254" );
                        _icelandicRange.AddRange( "193.4.0.1", "193.4.255.254" );
                        _icelandicRange.AddRange( "194.144.0.1", "194.144.255.254" );
                        _icelandicRange.AddRange( "213.176.128.1", "213.176.159.254" );
                        _icelandicRange.AddRange( "213.213.128.1", "213.213.159.254" );
                        _icelandicRange.AddRange( "217.9.128.1", "217.9.143.254" );
                        _icelandicRange.AddRange( "217.151.160.1", "217.151.191.254" );
                        _icelandicRange.AddRange( "213.190.96.1", "213.190.127.254" );
                        _icelandicRange.AddRange( "193.109.16.1", "193.109.31.254" );
                }

                return _icelandicRange;
        }

        private class SingleIPRange {

                private String[] arr1;
                private String[] arr2;
                private Range first;
                private Range second;
                private Range third;
                private Range fourth;
                private String firstIP;
                private String lastIP;

                public SingleIPRange( String ip1, String ip2 ) {

                        firstIP = ip1;
                        lastIP = ip2;

                        arr1 = ip1.Split( DOT_PATTERN );
                        arr2 = ip2.Split( DOT_PATTERN );

                        first = RangeFromArrayIndex( 0 );
                        second = RangeFromArrayIndex( 1 );
                        third = RangeFromArrayIndex( 2 );
                        fourth = RangeFromArrayIndex( 3 );
                }

                public bool IsInRange( String ipAddress ) {

                        if( string.IsNullOrEmpty( ipAddress ) )
                                return false;

                        String[] a = ipAddress.Split( DOT_PATTERN );

                        if( first.ContainsLocation( int.Parse( a[0] ) ) )
							if (second.ContainsLocation(int.Parse(a[1])))
								if (third.ContainsLocation(int.Parse(a[2])))
									if (fourth.ContainsLocation(int.Parse(a[3])))
										return true;

                        return false;
                }

                private Range RangeFromArrayIndex( int i ) {
                        int addr1 = int.Parse( arr1[i] );
                        int addr2 = int.Parse( arr2[i] );

                        int length = addr2 - addr1 + 1;

                        return new Range( addr1, length );
                }

                public String ToString() {
                        return firstIP + " - " + lastIP;
                }
        }

        public String ToString() {
			StringBuilder b = new StringBuilder();

                foreach ( SingleIPRange s in ranges ) {
                        b.Append( s );
                        b.Append( LF );
                }

                return b.ToString();
        }

        private class Range {

                public Range( int newStart, int newLength ) {
                        start = newStart;
                        length = newLength;
                }

                int start;
                int length;

                public bool ContainsLocation( int location ) {
                        return IsBetween( location, start, start + length );
                }

				private bool IsBetween(int number, int from, int to) {

					if (number == null || from == null || to == null) {
						return false;
					}

					int doubleNumber = number;
					int floor = from;
					int ceiling = to;

					if ((doubleNumber >= floor) && (doubleNumber <= ceiling)) {
						return true;
					}

					return false;
				}

        }
}

	}

